package code.whmmm.util.thread;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import code.whmmm.util.spring.quartz.task.LogWrapCallable;
import code.whmmm.util.spring.quartz.task.LogWrapRunnable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

/**
 * 线程工具类 <br/>
 * <b>由此工具类创建的线程名称: thread-manager-pool-** </b><br/>
 * 创建时间 2019年8月26日 15:29:50
 * <pre>{@code
 *
 *     // 线程池配置
 *     new ThreadPoolExecutor(5,   //corePoolSize 最小线程数
 *                            200,   // maxSize 最大线程数
 *                            24,  // timeout ,默认为 24 小时
 *                            TimeUnit.HOURS, // 时间单位， 小时
 *                            new LinkedBlockingQueue<Runnable>(1024), // 线程等待队列
 *
 *                            // 线程工厂
 *                            new NormalThreadBuilder("thread-manager-pool"),
 *
 *                            new ThreadPoolExecutor.AbortPolicy() // 策略
 *                           );
 *
 * }</pre>
 *
 * @author Zero
 */
public class ThreadManager {

    private final ExecutorService pool;


    private String threadPoolName;


    /**
     * 创建 threadManager <br/>
     * 默认名: thread-manager-pool
     *
     * @param pooName  线程池名称
     * @param coreSize 线程池大小
     */
    public ThreadManager(String pooName, int coreSize) {

        if (coreSize <= 0) {
            coreSize = 5;
        }

        if (null == pooName || "".equals(pooName)) {
            threadPoolName = "thread-manager-pool";
        } else {
            threadPoolName = pooName;
        }

        ThreadFactory namedThreadFactory = new NormalThreadBuilder(threadPoolName);
        pool = new ThreadPoolExecutor(
                coreSize, 200,
                24, TimeUnit.HOURS,
                new LinkedBlockingQueue<Runnable>(1024),
                namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
    }


    // spring 自动注入

    private static final Logger log = LoggerFactory.getLogger(ThreadManager.class);


    /**
     * 使用线程池 执行多个 Runnable
     *
     * @param blockMainThread 是否阻塞主线程.
     * @param runnable        实现了 Runnable 的对象
     * @param <T>             实现了 Runnable 的 类...
     */
    public final <T extends Runnable> void execute(boolean blockMainThread, T... runnable) {
        List<Future<?>> list = new ArrayList<Future<?>>();
        if (runnable != null && runnable.length > 0) {
            for (Runnable it : runnable) {
                if (it != null) {
                    Future<?> future = pool.submit(it);
                    list.add(future);
                }
            }
        }

        if (blockMainThread) {
            for (Future<?> it : list) {
                try {
                    it.get();
                } catch (Exception e) {
                    log.error("ThreadManager 类线程池异常! -" + e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 使用线程池 执行多个 Runnable <br/>
     * 已经做了 判空操作，无需再判断为空
     *
     * @param blockMainThread 是否阻塞主线程.
     * @param list            实现了 Runnable 列表 List
     * @param <T>             实现了 Runnable 的 类...
     */
    public <T extends Runnable> void execute(boolean blockMainThread, List<T> list) {

        if (list == null || list.size() == 0) {
            return;
        }

        Runnable[] array = list.toArray(new Runnable[]{});

        execute(blockMainThread, array);

    }

    /**
     * 执行线程
     *
     * @param t   Runnable 示例
     * @param <T> ? extends  Runnable
     */
    public <T extends Runnable> void execute(T t) {
        pool.execute(t);
    }

    public ExecutorService getPool() {
        return pool;
    }


    /**
     * 启动 多个 callable 线程
     *
     * @param blockMainThread true 阻塞, false 非阻塞
     * @param t               线程数组
     * @param <T>             继承的 callable 类型
     * @param <R>             callable 的 返回值类型
     * @return {@code List<R>} 执行结果，包括 null 结果 ,只有 blockMainThread 为true时有效
     */
    public final <T extends Callable<R>, R> List<R> submit(boolean blockMainThread, T... t) {
        List<Future<R>> list = new ArrayList<Future<R>>();
        List<R> resultList = new ArrayList<R>();
        if (t != null && t.length > 0) {
            for (Callable<R> it : t) {
                if (it != null) {
                    Future<R> future = pool.submit(it);
                    list.add(future);
                }
            }
        }

        if (blockMainThread) {
            for (Future<R> it : list) {
                try {

                    R temp = it.get();

                    resultList.add(temp);

                } catch (Exception e) {
                    log.error("ThreadManager 类线程执行异常! -" + e.getMessage(), e);
                }
            }
        }

        return resultList;
    }


    /**
     * 启动 多个 callable 线程
     *
     * @param blockMainThread true 阻塞, false 非阻塞
     * @param list            线程 Collection 集合
     * @param <T>             继承的 callable 类型
     * @param <R>             callable 的 返回值类型
     * @return {@code List<R>} 执行结果，包括 null 结果,只有 blockMainThread 为 true 时有效
     */
    @SuppressWarnings("unchecked")
    public <T extends Callable<R>, R> List<R> submit(boolean blockMainThread,
                                                     Collection<T> list) {
        if (list == null || list.size() == 0) {
            return new ArrayList<R>();
        }
        Callable[] callAbles = list.toArray(new Callable[]{});
        if (callAbles.length > 0) {
            return submit(blockMainThread, callAbles);
        }
        return new ArrayList<R>();
    }

    /**
     * 执行 callable
     *
     * @param t   Callable 示例
     * @param <T> 类型
     * @param <R> 返回值类型
     * @return {@code Future<R>}
     */
    public final <T extends Callable<R>, R> Future<R> submit(T t) {
        return pool.submit(t);
    }

    /**
     * 执行线程，如果 callable 。<br/>
     * 如果  callable 的 isEnable = false，则不执行线程！
     *
     * @param callable {@link LogWrapCallable}
     * @return
     */
    public final Future<Integer> submit(LogWrapCallable callable) {
        if (callable == null) {
            return null;
        }
        if (!callable.isEnable()) {
            return null;
        }
        return pool.submit(callable);
    }

    /**
     * 执行线程
     *
     * @param runnable
     */
    public final void execute(LogWrapRunnable runnable) {
        if (runnable == null) {
            return;
        }
        if (!runnable.isEnable()) {
            return;
        }
        pool.execute(runnable);
    }
}
